#pragma once


#include <string>
#include <string.h>
#include <jsoncpp/json/json.h>/*json解决序列化和反序列化的问题*/

namespace protocol
{
#define SEP " "
#define SEP_LEN strlen(SEP)
#define LINE "\r\n"
#define LINE_LEN strlen(LINE)

    /*从网络当中获取请求*/
    bool getRequest(int sock,std::string &rqs)
    {
        std::string inbuffer;
        while(true)
        {
            char buffer[1024];
            ssize_t n = recv(sock,buffer,sizeof(buffer),0);
            if(n > 0)
            {
                buffer[n] = 0;
                inbuffer += buffer;
                auto pos = inbuffer.find(LINE);
                if(pos == std::string::npos) continue;

                /*现在保证了一定有一个LINE，意味着一定拿到了报头*/
                std::string headers = inbuffer.substr(0,pos);
                int length = std::stoi(headers);
                int total_length = length + LINE_LEN*2 + headers.size();
                if(inbuffer.size() < total_length) continue;

                /*到这里，至少拿到了一个完整的报文*/
                rqs = inbuffer.substr(0,total_length);
                inbuffer.erase(0,total_length);

                break;
            }
            else return false;
        }
        return true;
    }

    /*添加报头(向下封装)，封装之后的字符串作返回值
     *格式:length\r\ntext\r\n*/
    std::string addHeaders(const std::string &str)
    {
        std::string headers = std::to_string(str.size());
        headers += LINE;
        headers += str;
        headers += LINE;

        return headers;
    }

    /*去掉报头(向上解包)，参数为输出型参数*/
    bool delHeaders(std::string &str)
    {
        auto pos = str.find(LINE);
        if(pos == std::string::npos) return false;
        std::string headers = str.substr(0,pos);/*拿到了报头*/
        int length = std::stoi(headers);
        str = str.substr(pos + LINE_LEN,length);
        return true;
    }

    /*协议定制
     *Request:规定服务端请求的报文格式
     *Response:规定服务器应答的报文格式*/
    class Request
    {
    public:
        Request(int left = 0,int right = 0,char oper = 0)
            :_left(left),_right(right),_oper(oper)
        {}

        /*请求序列化:输出型参数
         *"left oper right"*/
        bool serialize(std::string &out)
        {
#ifdef MYSELF
            out.clear();
            out += std::to_string(_left);
            out += SEP;
            out += _oper;
            out += SEP;
            out += std::to_string(_right);
#else
            Json::Value root;
            root["left"] = _left;
            root["right"] = _right;
            root["oper"] = _oper;
            Json::FastWriter writer;
            out = writer.write(root);
#endif
            return true;
        }

        /*请求反序列化*/
        bool deserialize(const std::string &str)
        {
#ifdef MYSELF
            auto left = str.find(SEP);
            auto right = str.rfind(SEP);
            if(left == std::string::npos || right == std::string::npos) return false;
            if(left == right) return false;/*只有一个空格，不合法*/
            if(right - (left+SEP_LEN) != 1) return false;/*运算符只占一个字节*/

            std::string left_string = str.substr(0,left);
            std::string right_string = str.substr(right+SEP_LEN);
            if(left_string.empty() || right_string.empty()) return false;
            _left = std::stoi(left_string);
            _right = std::stoi(right_string);
            _oper = str.substr(left+SEP_LEN,1)[0];
#else
            Json::Value root;
            Json::Reader reader;
            reader.parse(str,root);/*分析str到root里面去*/
            
            _left = root["left"].asInt();
            _right = root["right"].asInt();
            _oper = root["oper"].asInt();
#endif
            return true;
        }
        int _left;
        int _right;
        char _oper;
    };

    class Response
    {
    public:
        Response(int exitCode = 0,int result = 0)
            :_exitCode(exitCode),_result(result)
        {}

        /*响应序列化:输出型参数
         *"exitCode result"*/
        bool serialize(std::string &out)
        {
#ifdef MYSELF
            out.clear();
            out += std::to_string(_exitCode);
            out += SEP;
            out += std::to_string(_result);
#else
            Json::Value root;
            root["exitCode"] = _exitCode;
            root["result"] = _result;
            Json::FastWriter writer;
            out = writer.write(root);
#endif
            return true;
        }

        /*响应反序列化*/
        bool deserialize(const std::string &str)
        {
#ifdef MYSELF
            auto pos = str.find(SEP);
            if(pos == std::string::npos) return false;
            _exitCode = std::stoi(str.substr(0,pos));
            _result = std::stoi(str.substr(pos + SEP_LEN));
#else
            Json::Value root;
            Json::Reader reader;
            reader.parse(str,root);
            _exitCode = root["exitCode"].asInt();
            _result = root["result"].asInt();
#endif
            return true;
        }
        int _exitCode;
        int _result;
    };
}/*namespace protocol ends here*/